package com.sduept.nwld.dataserver.controller.document;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;

import org.primefaces.PrimeFaces;
import org.primefaces.event.CellEditEvent;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.event.NodeExpandEvent;
import org.primefaces.event.NodeSelectEvent;
import org.primefaces.event.ReorderEvent;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.StreamedContent;
import org.primefaces.model.TreeNode;
import org.primefaces.model.UploadedFile;
import org.springframework.beans.factory.annotation.Autowired;

import com.sduept.bigdata.document.core.CommonDocumentProperties;
import com.sduept.bigdata.document.entity.core.CommonDocument;
import com.sduept.bigdata.document.entity.core.CommonDocumentDir;
import com.sduept.bigdata.document.services.CommonDocumentService;
import com.sduept.bigdata.equipment.assessment.enums.DirTypeEnum;
import com.sduept.bigdata.web.jsf.controller.AbstractController;
import com.sduept.generator.ObjectId;
import com.sduept.nwld.dataserver.util.LibTreeNode;
import com.sduept.utils.ListUtils;

@Named
@ViewScoped
public class CommonDocumentController extends AbstractController implements
		Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = -4306592078623341306L;
	@Autowired
	private CommonDocumentService docService;
	@Autowired
	private CommonDocumentProperties commonDocumentProperties;
	private TreeNode root;
	private TreeNode currentSelectedNode;
	
	private List<CommonDocumentDir> documentDirs;// 所有的文档目录
	private List<CommonDocumentDir> tempDirs = new ArrayList<>();// 一个目录下的文档目录
	private List<CommonDocument> list;//某个目录下的所有文档
	private CommonDocumentDir createDir;//新建目录
	private CommonDocumentDir selected = null;//选中的目录
	private CommonDocument selectedDoc;//选中的文档记录
	private StreamedContent file;


	private Integer docYear = null;// 文档所属年份
	private Integer docMonth = null;// 文档所属月份
	private int currentSelectOrder = -1;
	/**
	 * 是否将上传的文档进行拆分保存，以备文档内容快速检索
	 */
	private boolean splitdoc;
	@PostConstruct
	public void init() {
		initTree();
	}

	public void initTree() {
		try {
			documentDirs = docService.findAllDocumentDir();
			root = new DefaultTreeNode();
			LibTreeNode firstNode = new LibTreeNode("rootDir", "文档目录", root);
			
			List<CommonDocumentDir> rootDirs = new ArrayList<>();
			for (CommonDocumentDir dir : documentDirs) {
				if (dir.getPid() == null) {
					rootDirs.add(dir);
				}
			}
			sortByOrderNo(rootDirs);
			for (CommonDocumentDir d : rootDirs) {
				new LibTreeNode(CommonDocumentDir.class.getSimpleName(), d, firstNode);
			}
			firstNode.setExpanded(true);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/*
	 * 按orderNo升序 排序
	 */
	private void sortByOrderNo(List<CommonDocumentDir> dirs) {
		Collections.sort(dirs, new Comparator<CommonDocumentDir>() {
			@Override
			public int compare(CommonDocumentDir o1, CommonDocumentDir o2) {
				return o1.getOrderNo() - o2.getOrderNo();
			}
		});
	}

	/*
	 * 新建目录
	 */
	public void preCreate() {
		createDir = new CommonDocumentDir();
		createDir.setCreateDate(new Date());
		createDir.setCreater(getCurrentUser().getCode());
	}

	public void createDir() {
		try {
			List<CommonDocumentDir> ds = new ArrayList<>();
			if (selected != null) {
				createDir.setPid(selected.getId());
			}
				ds=docService.findDocumentDirByPid(createDir.getPid());
			for(CommonDocumentDir d:ds){
				if (d.getName().equals(createDir.getName())) {
					addErrorMessage(createDir.getName() + "已存在");
					return;
				}
			}
			createDir.setOrderNo(ds.size());
			createDir.setId(ObjectId.get().toString());
			docService.createOrUpdateDocumentDir(createDir);
			documentDirs.add(createDir);
			//树
			if(currentSelectedNode.isExpanded()) {
				//如果该节点已经展开，直接new出新建的节点
				new DefaultTreeNode("CommonDocumentDir", createDir, currentSelectedNode);
				tempDirs.add(createDir);
			}else {
				currentSelectedNode.setExpanded(true);
				genSubTreeNode(currentSelectedNode);
			}
			addSuccessMessage("新建目录成功");
		} catch (Exception e) {
			e.printStackTrace();
			addErrorMessage("新建目录失败");
		}
	}
	
	/*
	 * 编辑目录
	 */
	public void editDir() {
		try {
			selected.setCreateDate(new Date());
			selected.setCreater(getCurrentUser().getCode());
	
			// 判断orderNo有没有变
			if (currentSelectOrder != -1
					&& currentSelectOrder != selected.getOrderNo()) {
				resetOrderNo(selected);
			}else{
				docService.createOrUpdateDocumentDir(selected);
			}
			currentSelectOrder = selected.getOrderNo();
			//setParentNodeSelected();
			genSubTreeNode(currentSelectedNode);
			addSuccessMessage("编辑目录成功");
		}catch(Exception e) {
			addErrorMessage("编辑目录失败");
		}
	}
	
	/**
	 * 设置父节点为选中的节点
	 */
	private void setParentNodeSelected() throws Exception{
		currentSelectedNode=currentSelectedNode.getParent();
		currentSelectedNode.getChildren().clear();
		currentSelectedNode.setSelected(true);
//		  selected=(CommonDocumentDir)currentSelectedNode.getData();
//		  list = docService.findDocumensByDirId(selected.getId());
		/**
		 * @author pengz
		 */
		Object parentData = currentSelectedNode.getData();
		if(parentData instanceof CommonDocumentDir) {
			selected=(CommonDocumentDir)parentData;
			list = docService.findDocumensByDirId(selected.getId());
		}else {
			selected = null;
		}
		 
	}

	/**
	 * 重置顺序
	 * @param selectedDir
	 */
	private void resetOrderNo(CommonDocumentDir selectedDir) throws Exception{
		
		int newOrderNO=selectedDir.getOrderNo();
		if (!tempDirs.contains(selectedDir)) {
			//删除目录
			for(int i=newOrderNO;i<tempDirs.size();i++){
				tempDirs.get(i).setOrderNo(i);
				docService.createOrUpdateDocumentDir(tempDirs.get(i));
			}
		}else{
			List<CommonDocumentDir> ds=ListUtils.sortListByOrderNo(tempDirs,currentSelectOrder,newOrderNO,"orderNo");
			if(ds.size()>0){
				for (CommonDocumentDir tmp : ds) {
					docService.createOrUpdateDocumentDir(tmp);
				}
			}else{
				addErrorMessage("编辑失败!");
			}
		}
	}

	// 删除目录
	public void deleteDir() {
		try {
			if (selected == null) {
				addErrorMessage("请选择一个目录");
				return;
			}
			// 删除该目录下所有的目录和文档
			docService.deleteDirs(selected);
			documentDirs.remove(selected);
			tempDirs.remove(selected);
			/**
			 * 重置顺序有错。。。
			 */
			resetOrderNo(selected);//已经没有该元素
			currentSelectOrder = selected.getOrderNo();
			setParentNodeSelected();
//			genSubTreeNode(currentSelectedNode);
			/**
			 * @author pengz
			 */
			if(selected!=null) {
				genSubTreeNode(currentSelectedNode);
			}else {
				initTree();
			}
			
			addSuccessMessage("删除成功");
		} catch (Exception e) {
			e.printStackTrace();
			addErrorMessage("删除失败");
		}
	}

	public void onNodeExpand(NodeExpandEvent event) {
		try {
			TreeNode currentNode = event.getTreeNode();
			if ("CommonDocumentDir".equals(currentNode.getType())) {
				genSubTreeNode(currentNode);
			}
		}catch(Exception e) {
			e.printStackTrace();			
		}
		
	}
	private void genSubTreeNode(TreeNode currentNode)throws Exception {
		if(tempDirs.size()>0) {
			tempDirs.clear();
			currentNode.getChildren().clear();
		}
		CommonDocumentDir currentObj = (CommonDocumentDir) currentNode.getData();
		for (CommonDocumentDir d : documentDirs) {
			if (d.getPid() != null && d.getPid().equals(currentObj.getId())) {
				tempDirs.add(d);
			}
		}
		sortByOrderNo(tempDirs);
		for (CommonDocumentDir d : tempDirs) {
			new LibTreeNode("CommonDocumentDir", d, currentNode);
		}
	}
	public void onNodeSelect(NodeSelectEvent event) {
		try {
			if ("CommonDocumentDir".equals(currentSelectedNode.getType())) {
				selected = (CommonDocumentDir) currentSelectedNode.getData();
				currentSelectOrder = selected.getOrderNo();
				list = docService.findDocumensByDirId(selected.getId());
			} else {
				selected = null;
			}
		}catch(Exception e) {
			
		}
	}

	// 上传前清空year和month
	public void preUpload() {
		docYear = null;
		docMonth = null;
	}
	/**
	 * 
	 * @param event
	 */
	public void handleFileUpload(FileUploadEvent event) {
		UploadedFile file = event.getFile();
		String fileName=file.getFileName();		
		String houzhuiming = fileName.substring(fileName.lastIndexOf("."));
		String id = ObjectId.get().toString();
		String filePathName = id + houzhuiming;
		//String uploadpath = SystemProperties.DOCUMENT_PATH + filePathName;
		try {
			CommonDocument ra = new CommonDocument();
			ra.setName(fileName);
			ra.setId(id);
			ra.setDirId(selected.getId());
			//系统配置路径的相对路径
			ra.setPath(filePathName);
			ra.setDescription(file.getFileName());
			ra.setCreateDate(new Date());
			ra.setUploadCode(getCurrentUser().getCode());
			ra.setUploadPerson(getCurrentUser().getName());
			ra.setUploadDate(new Date());
			ra.setOrderNo(list.size()+1);
			ra.setType(DirTypeEnum.EVALUATE.getDirType());
			//docService.upload(ra, uploadpath, file.getContents());
			docService.upload(ra, file.getContents(), splitdoc);
			list.add(ra);
			/*
			 * if(splitdoc) { docService.generateDocumentContent(ra,uploadpath); }
			 */
			addSuccessMessage("上传成功");
		} catch (Exception ee) {
			ee.printStackTrace();
			addErrorMessage("上传失败");
		}
	}
	 public void onRowReorder(ReorderEvent event) {
		 //从0开始
		 try {
			 resetDocListOrderNo();
		 }catch(Exception e) {
			 e.printStackTrace();
		 }
	}
	// 文件下载
	public void fileDownloadView(CommonDocument target) {
		selectedDoc=target;
		try {
			InputStream stream = new FileInputStream(new File(
					commonDocumentProperties.getDocumentPath()+selectedDoc.getPath()));
//			String fname = CharacterUtil.urlEncode(selectedDoc.getName());
			file = new DefaultStreamedContent(stream,
					"application/octet-stream",selectedDoc.getName() );

		} catch (FileNotFoundException e) {
			e.printStackTrace();
			addErrorMessage("下载失败");
		}
	}

	// 文件删除
	public void removeSelectDocument(CommonDocument ra) {
		selectedDoc=ra;
		try {
			docService.deleteDocument(ra);
			list.remove(ra);
			resetDocListOrderNo();
			addSuccessMessage("删除成功");
		} catch (Exception e) {
			e.printStackTrace();
			addErrorMessage("删除失败");
		}
	}
	
	// 文件转移文件夹
	public void moveSelectDocument(CommonDocument target) {
		selectedDoc=target;
		Map<String,Object> options = new HashMap<String, Object>();
        options.put("resizable", false);
        options.put("draggable", false);
        options.put("modal", true);
        options.put("width",350);
        options.put("height",400);
        //openDialog("/ui/document/common_document_dir_selector.xhtml", options, null);
        PrimeFaces.current().dialog().openDynamic("/ui/document/common_document_dir_selector.xhtml", options, null);
	}
	
	
	public void openDocumentSelector(String rootType) {
		Map<String,Object> options = new HashMap<String, Object>();
        options.put("resizable", false);
        options.put("draggable", false);
        options.put("modal", true);
        options.put("width",400);
        options.put("height",500);
        Map<String,List<String>> params = new HashMap<>();
        List<String> rootTypes = new ArrayList<>();  
        rootTypes.add(rootType);
        params.put("rootTypes", rootTypes);
        //openDialog("/ui/document/common_document_multiple_selector.xhtml",  params,options);
        PrimeFaces.current().dialog().openDynamic("/ui/document/common_document_multiple_selector.xhtml",  options,params);
	}
	
	public void onDirChosen(SelectEvent event) {
		try {
			CommonDocumentDir selectedMovedDir=(CommonDocumentDir) event.getObject();
			if(!selectedMovedDir.getId().equals(selected.getId())){
				list.remove(selectedDoc);
				resetDocListOrderNo();
			}
			selectedDoc.setDirId(selectedMovedDir.getId());
			List<CommonDocument> docs=docService.findDocumensByDirId(selectedMovedDir.getId());
			selectedDoc.setOrderNo(docs.size()+1);
			docService.createOrUpdateRecordDocument(selectedDoc);
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
    //刷新docs的文档序号
	private void resetDocListOrderNo() throws Exception{		
		int index=1;
	    for(CommonDocument d:list){
	    	d.setOrderNo(index);
	    	index++;
	    	docService.createOrUpdateRecordDocument(d);
	    }
	}
	//修改文件名
	public void onCellEdit(CellEditEvent event) {
		try {
        Object oldValue = event.getOldValue();
        Object newValue = event.getNewValue();
        int rowIndex=event.getRowIndex();
			CommonDocument d=list.get(rowIndex);
        if(newValue != null && !newValue.equals(oldValue)) {
        	docService.createOrUpdateRecordDocument(d);
        	}
       }catch(Exception e) {
    	   e.printStackTrace();
        }
    }
	public CommonDocumentDir getCreateDir() {
		return createDir;
	}

	public void setCreateDir(CommonDocumentDir current) {
		this.createDir = current;
	}

	public CommonDocumentDir getSelected() {
		return selected;
	}

	public void setSelected(CommonDocumentDir selected) {
		this.selected = selected;
	}

	public StreamedContent getFile() {
		return file;
	}

	public void setFile(StreamedContent file) {
		this.file = file;
	}

	public TreeNode getRoot() {
		return root;
	}

	public void setRoot(TreeNode root) {
		this.root = root;
	}

	public Integer getDocYear() {
		return docYear;
	}

	public void setDocYear(Integer docYear) {
		this.docYear = docYear;
	}

	public Integer getDocMonth() {
		return docMonth;
	}

	public void setDocMonth(Integer docMonth) {
		this.docMonth = docMonth;
	}

	public List<CommonDocument> getList() {
		return list;
	}

	public void setList(List<CommonDocument> list) {
		this.list = list;
	}

	public TreeNode getCurrentSelectedNode() {
		return currentSelectedNode;
	}

	public void setCurrentSelectedNode(TreeNode currentSelectedNode) {
		this.currentSelectedNode = currentSelectedNode;
	}


	public CommonDocument getSelectedDoc() {
		return selectedDoc;
	}

	public void setSelectedDoc(CommonDocument selectedDoc) {
		this.selectedDoc = selectedDoc;
	}

	public boolean isSplitdoc() {
		return splitdoc;
	}

	public void setSplitdoc(boolean splitdoc) {
		this.splitdoc = splitdoc;
	}

	

}
